using System.IO;
using System.Xml;
using HCore.Core;
using HCore.IOC.Beans.Factory.Attribute.Attr;
using HCore.Unity.Behaviour;
using HCore.Unity.Core;
using HCore.Unity.Manager;
using UnityEngine;
using UnityEngine.UI;

namespace HCore.Tests.Runtime.ShootingEditor2D.Scripts.ViewController.LevelEditor
{
    /// <summary>
    ///     关卡播放器类，用于加载并运行用户自定义的关卡文件。
    ///     该类继承自 HCoreMonoBehaviour，支持状态切换（选择/播放）和动态生成 UI 按钮以加载关卡。
    /// </summary>
    public class LevelPlayer : HCoreMonoBehaviour
    {
        private readonly BindableProperty<State> mCurrentState = new();

        [Autowired] private PrefabManager mPrefabManager;
        private static string LevelFilesFolder => $"{Application.persistentDataPath}/LevelFiles";

        /// <summary>
        ///     在对象被唤醒时调用，注册状态变更监听器并触发初始状态。
        /// </summary>
        protected override void Awake()
        {
            base.Awake();
            mCurrentState.Register(ActionStateChanged).Trigger();
        }

        /// <summary>
        ///     在对象被销毁前调用，注销状态变更监听器。
        /// </summary>
        protected override void OnDestroy()
        {
            mCurrentState.UnRegister(ActionStateChanged);
            base.OnDestroy();
        }

        /// <summary>
        ///     状态变更处理函数。根据当前状态决定是显示关卡选择界面还是清理画布。
        /// </summary>
        /// <param name="currentState">当前状态</param>
        /// <param name="_">上一个状态（未使用）</param>
        private void ActionStateChanged(State currentState, State _)
        {
            // 如果当前状态为选择状态，则读取所有关卡文件并创建按钮
            if (currentState == State.Selection)
            {
                var filePaths = Directory.GetFiles(LevelFilesFolder);
                foreach (var filePath in filePaths) BuildButton(filePath);
            }
            // 否则清除画布上的所有子对象
            else
            {
                foreach (Transform trans in GameUtils.MainCanvas.transform) Destroy(trans.gameObject);
            }
        }

        /// <summary>
        ///     根据指定的文件路径创建一个按钮，并设置其文本和点击事件。
        /// </summary>
        /// <param name="filePath">关卡文件的完整路径</param>
        /// <returns>创建的按钮 GameObject</returns>
        private GameObject BuildButton(string filePath)
        {
            var fileName = Path.GetFileName(filePath);
            var canvasTransform = GameUtils.MainCanvas.transform;
            var buttonGo = mPrefabManager.LoadPrefabGameObject("Prefab/Button", canvasTransform);
            buttonGo.GetComponentInChildren<Text>().text = fileName;
            buttonGo.transform.localPosition = new Vector3(-300f, 330 - (canvasTransform.childCount - 1) * 60,
                buttonGo.transform.position.z);
            buttonGo.GetComponent<Button>().onClick.AddListener(() => ParseAndRun(filePath));
            return buttonGo;
        }

        /// <summary>
        ///     解析指定路径的 XML 关卡文件，并根据内容实例化对应的预制体。
        /// </summary>
        /// <param name="filePath">要解析的关卡文件路径</param>
        private void ParseAndRun(string filePath)
        {
            mCurrentState.Value = State.Playing;

            var xml = File.ReadAllText(filePath);
            // var xml = "";
            Debug.Log("开始解析关卡数据......");
            // var xml = levelFile.text;
            var document = new XmlDocument();
            document.LoadXml(xml);

            var levelNode = document.SelectSingleNode("Level");

            if (levelNode == null) return;

            // 遍历 Level 节点下的所有子节点，解析属性并加载对应预制体
            foreach (XmlNode levelItemNode in levelNode.ChildNodes)
            {
                var levelItemName = levelItemNode.Attributes?["name"].Value;
                var levelItemX = levelItemNode.Attributes?["x"].Value;
                var levelItemY = levelItemNode.Attributes?["y"].Value;

                var levelItemGo = mPrefabManager.LoadPrefabGameObject($"Prefab/{levelItemName}", transform);
                levelItemGo.transform.position = new Vector3(int.Parse(levelItemX!), int.Parse(levelItemY!), 0);

                Debug.Log($"name: ${levelItemName}: [{levelItemX}, {levelItemY}]");
            }
        }

        /// <summary>
        ///     定义关卡播放器的状态枚举。
        /// </summary>
        private enum State
        {
            /// <summary>
            ///     选择关卡状态，显示可选关卡列表。
            /// </summary>
            Selection,

            /// <summary>
            ///     播放关卡状态，加载并运行选中的关卡。
            /// </summary>
            Playing
        }
    }
}